#include "game_http.h"
#include "game_util.h"
#include <sys/stat.h>
#include <event2/buffer.h>

using namespace CGame::Httpd;

void CGame::Httpd::__evhttpd_set_content_lenght(evkeyvalq *headers, size_t len)
{
  char str[64] = {0};
  snprintf(str, sizeof(str), "%lu\n", (unsigned long)len);
  evhttp_add_header(headers, "Content-Length", str);
}

void __evhttpd_set_server(evkeyvalq *headers, const char *s)
{
  evhttp_add_header(headers, "Server", s);
}

Response::Response(CGameHttpd *master):_master(master){

}


void Response::header(Request *req, const char *name, const char *val)
{
  evkeyvalq *outhead = evhttp_request_get_output_headers(req->_request);
  __debug("header is %p\n", outhead);
  evhttp_add_header(outhead, name, val);
}

void Response::cookie(Request *req, const char *name, const char *val)
{
  cookie(req, name, val, 0);
}

void Response::cookie(Request *req, const char *name, const char *val, CookieExpires_t expires)
{

  do
  {
    char cookie[1024];
    if (0 != expires)
    {
      char gmt[30];
      size_t ret = __gmtime_add(expires, gmt);
      CC_BREAK_IF_LOG(0 > ret, "%s", "err when get gmt");
      snprintf(cookie, sizeof(cookie), "%s=%s;path=/;expires=%s", name, val, gmt);
    }
    else
      snprintf(cookie, sizeof(cookie), "%s=%s", name, val);
    header(req, "Set-Cookie", cookie);

  } while (false);
}

void Response::redirect(Request *req, const char *dest)
{
  redirect(req, dest, HTTP_MOVETEMP);
}

void Response::redirect(Request *req, const char *dest, int status)
{
  HttpdRequest_t* request = req->_request;
  evkeyvalq *outhead = evhttp_request_get_output_headers(request);
  evhttp_add_header(outhead, "Location", dest);
  send(req, status);
}

void Response::stream(Request *req, int fd, const char *ext)
{
  HttpdRequest_t* request = req->_request;
  evkeyvalq *outhead = evhttp_request_get_output_headers(request);
  // const char *ext = pos + 1;
  const char *mediaType = MediaType::getContentType(ext);
  evhttp_add_header(outhead, "Content-Type", mediaType);

  char str[64] = {0};
  struct stat buf;
  fstat(fd, &buf);
  snprintf(str, sizeof(str), "%ld\n", buf.st_size);
  evhttp_add_header(outhead, "Content-Length", str);
  evhttp_add_header(outhead, "Connection", "close");

  evbuffer *out = evhttp_request_get_output_buffer(request);
  if (0 == evbuffer_add_file(out, fd, 0, buf.st_size))
  {
    send(req, HTTP_OK);
  }
}

void Response::html(Request *req, const char *content)
{
  html(req, HTTP_OK, "%s", content);
}

void Response::html(Request *req, int status, const char *format, ...)
{
  va_list args;
  va_start(args, format);
  html(req, status, format, args);
  va_end(args);
}

void Response::html(Request *req, int status, const char *format, va_list args)
{
  HttpdRequest_t* request = req->_request;
  evkeyvalq *outhead = evhttp_request_get_output_headers(request);
  evhttp_add_header(outhead, "Content-Type", MediaType::TEXT_HTML_VALUE);
  evhttp_add_header(outhead, "Connection", "close");
  evbuffer *out = evhttp_request_get_output_buffer(request);
  int len = evbuffer_add_vprintf(out, format, args);
  CGame::Httpd::__evhttpd_set_content_lenght(outhead, len);
  send(req, status);
}

void Response::send(Request *req, int status)
{
  HttpdRequest_t *request = req->_request;
  evkeyvalq *outhead = evhttp_request_get_output_headers(request);
  __evhttpd_set_server(outhead, _master->vstring().c_str());
  evhttp_send_reply(request, status, NULL, NULL);
}
